﻿using System.Text;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;

namespace FarseerPhysics.SamplesFramework
{
    public class ActScreen : PhysicsGameScreen, IDemoScreen
    {
        private Border _border;
        private Actor _player;
        private List<Actor> _actors;
        private KeyMapping _testMapping;
        private ActInput _actInput;

        public ActInput ActInput {
            get { return _actInput; }
            set { _actInput = value; }
        }

        #region IDemoScreen Members

        public string GetTitle()
        {
            return "Action Game Test";
        }

        public string GetDetails()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("This demo shows a single body with one attached fixture and shape.");
            sb.AppendLine("A fixture binds a shape to a body and adds material");
            sb.AppendLine("properties such as density, friction, and restitution.");
            sb.AppendLine(string.Empty);
            sb.AppendLine("GamePad:");
            sb.AppendLine("  - Rotate object: left and right triggers");
            sb.AppendLine("  - Move object: right thumbstick");
            sb.AppendLine("  - Move cursor: left thumbstick");
            sb.AppendLine("  - Grab object (beneath cursor): A button");
            sb.AppendLine("  - Drag grabbed object: left thumbstick");
            sb.AppendLine("  - Exit to menu: Back button");
            sb.AppendLine(string.Empty);
            sb.AppendLine("Keyboard:");
            sb.AppendLine("  - Rotate Object: left and right arrows");
            sb.AppendLine("  - Move Object: A,S,D,W");
            sb.AppendLine("  - Exit to menu: Escape");
            sb.AppendLine(string.Empty);
            sb.AppendLine("Mouse / Touchscreen");
            sb.AppendLine("  - Grab object (beneath cursor): Left click");
            sb.AppendLine("  - Drag grabbed object: move mouse / finger");
            return sb.ToString();
        }

        #endregion

        public override void LoadContent()
        {
            base.LoadContent();

            _actInput = new ActInput();

            _testMapping = KeyMapping.CreateWSADMapping();

            World.Gravity = new Vector2(0, 30f);

            _border = new Border(World, this, ScreenManager.GraphicsDevice.Viewport);

            _actors = new List<Actor>();
            _player = new Actor(this);
            _actors.Add(_player);
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            // input.Update()
            _actInput.Update(gameTime);
            if (!coveredByOtherScreen && !otherScreenHasFocus)
            {
                HandleActInput();
            }
            // actor.Update()
            // 包括对Input做出响应
            foreach (var actor in _actors)
            {
                actor.Update();
            }
            // World.Update()
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }

        public override void Draw(GameTime gameTime)
        {
            _border.Draw();
            foreach (var actor in _actors)
            {
                actor.Draw();
            }
            base.Draw(gameTime);
        }

        public override void HandleInput(InputHelper input, GameTime gameTime)
        {
            
            HandleDebugViewControl(input);
            HandleCursor(input);
            if (input.IsNewButtonPress(Buttons.Back) || input.IsNewKeyPress(Keys.Escape))
            {
                ExitScreen();
            }
        }

        private void HandleActInput()
        {
            float maxMoveVelocity = 10f;
            float moveImpulse = maxMoveVelocity * _player.Body.Mass;
            float jumpImpulse = 15f * _player.Body.Mass;

            //if (ScreenManager.ActInput.IsKeyDown(_testMapping, FunctionKeys.Left))
            //{
            //    if (_player.Body.LinearVelocity.X > -maxMoveVelocity)
            //    {
            //        _player.Body.ApplyLinearImpulse(new Vector2(-moveImpulse, 0));
            //    }
            //}
            //else if (ScreenManager.ActInput.IsKeyDown(_testMapping, FunctionKeys.Right))
            //{
            //    if (_player.Body.LinearVelocity.X < maxMoveVelocity)
            //    {
            //        _player.Body.ApplyLinearImpulse(new Vector2(moveImpulse, 0));
            //    }
            //}
            //if (ScreenManager.ActInput.IsKeyTriggered(_testMapping, FunctionKeys.Jump))
            //{
            //    _player.Body.ApplyLinearImpulse(new Vector2(0, -jumpImpulse));
            //}
        }
    }
}